"""Functions for loading and using info files"""

import ConfigParser
import re
from pyre.core import types, dice

class InfoDB(object):
    """Represents the contents of an ini-style info file"""

    def __init__(self, filename, **converters):
        config = ConfigParser.ConfigParser()
        config.read(filename)

        self.data = {}
        for section in config.sections():
            self.data[section] = {}
            for key, value in config.items(section):
                if key in converters:
                    value = converters[key](value)
                elif section in converters:
                    value = converters[section](value)
                self.data[section][key] = value

    def __getitem__(self, name):
        return self.data[name]

    def query(self, name, **conditions):
        """
        InfoDB.query(str, **func): bool
        Returns True if the entry for the given name satisifies each of the
        given conditions. The conditions are single parameters functions which
        are passed the value of the entry keyed by the condition name
        """

        info = self.data[name]

        for key, condition in conditions.iteritems():
            if not condition(info[key]):
                return False
        return True

    def select(self, **conditions):
        """
        InfoDB.select(**func): list of str
        Returns a list of names of entries for query returns True with the
        given set of keyed conditions
        """

        return [name for name in self.data if self.query(name)]


def parse_tile(data):
    """
    parse_tile(str): ColoredChar
    Parses the data as a comma separated character-color pair
    """

    data = [x.strip() for x in data.split(',')]
    char, color = data[:2]
    sprite_id = None if len(data) < 3 else int(data[2])
    return types.ColoredChar(char, types.Color.try_by_name(color), sprite_id)


def parse_melee(data):
    """
    parse_melee(str): tuple
    Parses the data as a comman separated int-xdy pair
    """

    bonus, roll = (x.strip() for x in data.split(','))
    return int(bonus), parse_tuple(roll, 'd')


def parse_tuple(data, sep=','):
    """
    parse_tuple(str, chr): tuple of int
    Parses the data as a tuple of integers with the given separator
    """

    return tuple(int(x) for x in data.split(sep))


def parse_roll(data):
    """
    parse_roll(str): DiceRoll
    Returns a function which performs the indicated xdy roll
    """

    xdy = parse_tuple(data, 'd')
    return lambda : dice.roll_xdy(xdy)


def parse_bool(data):
    """
    parse_bool(str): bool
    Parses the string as a bool. If the string is 'true', 'yes', 'y', or 't'
    (ignoring case), then the result is True.
    """

    return data.lower() in ['true', 'yes', 'y', 't']


def parse_flags(data):
    """
    parse_flags(str): set of str
    Parse the comman separated list into a set of string flags
    """

    flags = {}
    for flag in data.split(';'):
        if ':' in flag:
            flag, value = flag.split(':', 1)
        else:
            value = None
        flags[flag] = value
    return flags
